#ifndef TB_REFLECTION_REFLECTION_HPP__
#define TB_REFLECTION_REFLECTION_HPP__

#include "../base/string.hpp"
#include "reflection_export.hpp"
#include "reflection_fwd.hpp"

TB_NAMESPACE_BEGIN

namespace reflection {

struct IRegisterWatcher {
  void OnRegisterBegin(uint32 typeId) { (void)typeId; }
  void OnParentRegistered(uint32 typeId, uint32 parentId) { (void)typeId, (void)parentId; }
  void OnMethodRegistered(uint32 typeId, Function* fn) { (void)typeId, (void)fn; }
  void OnPropertyRegistered(uint32 typeId, Property* prop) { (void)typeId, (void)prop; }
  void OnNamespaceRegistered(uint32 typeId, const TCHAR* nspace) { (void)typeId, (void)nspace; }
  void OnRegisterEnd(uint32 typeId) { (void)typeId; }
};
typedef _STD vector<IRegisterWatcher *> RegisterWatchersType;

TB_REFLECTION_API void RegisterBegin(uint32 typeId);
TB_REFLECTION_API void RegisterEnd(uint32 typeId);
TB_REFLECTION_API void AddRegisterWatcher(IRegisterWatcher *watcher);
TB_REFLECTION_API void RemoveRegisterWatcher(IRegisterWatcher *watcher);

TB_REFLECTION_API uint32 RegisterType(Allocator* allocator, const TCHAR* className, uint32 parentId = 0, uint32 interfaceId = 0, uint32 interfaceImplId = 0);
TB_REFLECTION_API void RegisterTypeName(uint32 typeId, const TCHAR* name);
TB_REFLECTION_API void RegisterNamespace(uint32 typeId, const TCHAR* nspace);
TB_REFLECTION_API void RegisterParent(uint32 typeId, uint32 parentId);
TB_REFLECTION_API void RegisterInterface(uint32 typeId, uint32 interfaceId, uint32 interfaceImplId);
TB_REFLECTION_API void RegisterConstructor(uint32 typeId, const Function* fn);
TB_REFLECTION_API void RegisterProperty(uint32 typeId, Property* property);
TB_REFLECTION_API void RegisterMethod(uint32 typeId, Function* fn);
TB_REFLECTION_API void RegisterContainer(uint32 typeId, uint32 firstType, uint32 secondType, CollectionEnumer* iterator);
TB_REFLECTION_API void RegisterPair(uint32 typeId, uint32 firstType, uint32 secondType);
TB_REFLECTION_API void RegisterGlobalFunction(const TCHAR* nspace, Function* fn);

typedef void (*BindingProcType)(void*);
typedef _STD vector<BindingProcType> BindingProcsType;
TB_REFLECTION_API void RegisterBindingProc(BindingProcType proc);

TB_REFLECTION_API const TypeNode* GetTypeRoot();
TB_REFLECTION_API uint32 GetTypeId(const TCHAR* className);
TB_REFLECTION_API const TypeNode* GetTypeNode(uint32 typeId);
TB_REFLECTION_API const TypeNode* GetTypeNode(const TCHAR* className);
TB_REFLECTION_API const TypeInfo* GetTypeInfo(uint32 typeId);
TB_REFLECTION_API const TypeInfo* GetTypeInfo(const TCHAR* className);
TB_REFLECTION_API const TCHAR* GetTypeName(uint32 typeId);
TB_REFLECTION_API const TCHAR* GetTypeDescription(uint32 typeId);
TB_REFLECTION_API ConstPropertiesType GetProperties(uint32 typeId);
TB_REFLECTION_API ConstFunctionsType GetFunctions(uint32 typeId);
TB_REFLECTION_API const Property* GetProperty(uint32 typeId, const TCHAR* propName);
TB_REFLECTION_API uint32 GetParent(uint32 typeId);
TB_REFLECTION_API void GetParents(uint32 typeId, std::vector<uint32>& ids, int depth = -1);
TB_REFLECTION_API const TypeInfo* GetParentInfo(uint32 typeId);
TB_REFLECTION_API void GetParentsInfo(uint32 typeId, std::vector<TypeInfo*>& infos, int depth = -1);
TB_REFLECTION_API void GetChildren(uint32 typeId, std::vector<uint32>& ids, int depth = -1);
TB_REFLECTION_API void GetChildrenInfo(uint32 typeId, std::vector<TypeInfo*>& infos, int depth = -1);
TB_REFLECTION_API const TCHAR* GetInheritancePath(uint32 typeId);
TB_REFLECTION_API ConstFunctionsType GetGlobalFunctions();
TB_REFLECTION_API BindingProcsType GetBindingProcs();

TB_REFLECTION_API void SetObjectPropertyValue(void* obj, Property* prop, const Variant* val, bool raw = false);

TB_REFLECTION_API Variant ConstructType(const TCHAR* className, bool isSharedPtr = true);
TB_REFLECTION_API Variant ConstructType(uint32 typeId, bool isSharedPtr = true);
TB_REFLECTION_API Variant ConstructType(const TypeInfo* typeInfo, bool isSharedPtr = true);
TB_REFLECTION_API void *ConstructRaw(const TCHAR* className);
TB_REFLECTION_API void *ConstructRaw(uint32 typeId);
TB_REFLECTION_API void *ConstructRaw(const TypeInfo* typeInfo);
TB_REFLECTION_API void DestroyType(uint32 typeId, void *data);
TB_REFLECTION_API Variant DeepCopy(const Variant* val);
TB_REFLECTION_API void DeepCopy(const void* src, void* dst, uint32 typeId);
TB_REFLECTION_API int CompareObject(const Variant* obj1, const Variant* obj2);

TB_REFLECTION_API bool IsKindOf(uint32 typeId, uint32 parentId);

} //namespace reflection

TB_NAMESPACE_END

#endif TB_REFLECTION_REFLECTION_HPP__
